﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestExtensions
{
	/// <summary>
	/// Contains assertion types that are not provided with the standard MSTest assertions.
	/// Specifically, allows for the testing of whether or not an exception was thrown.
	/// </summary>
	/// <remarks>
	/// From Scott Dorman's blog at http://geekswithblogs.net/sdorman/archive/2009/01/17/unit-testing-and-expected-exceptions.aspx.
	/// </remarks>
	public static class ExceptionAssert
	{
		/// <summary>
		/// Checks to make sure that the input delegate throws an exception of type TException.
		/// </summary>
		/// <typeparam name="TException">The type of exception expected.</typeparam>
		/// <param name="blockToExecute">The block of code to execute to generate the exception.</param>
		public static void Throws<TException>(Action blockToExecute)
			where TException : Exception
		{
			try
			{
				blockToExecute();
			}
			catch (Exception ex)
			{
				Assert.AreEqual(typeof(TException), ex.GetType(), string.Format("Expected expcetion of type {0} but type of {1} was thrown instead.", typeof(TException), ex.GetType()));
			}

			Assert.Fail(string.Format("Expected exception of type {0} but no exception was thrown.", typeof(TException)));
		}

		/// <summary>
		/// Checks to make sure that the input delegate throws an exception of type TException.
		/// </summary>
		/// <typeparam name="TException">The type of exception expected.</typeparam>
		/// <param name="expectedMessage">The message to be sent by the exception.</param>
		/// <param name="blockToExecute">The block of code to execute to generate the exception.</param>
		public static void Throws<TException>(string expectedMessage, Action blockToExecute)
			where TException : Exception
		{
			try
			{
				blockToExecute();
			}
			catch (Exception ex)
			{
				Assert.AreEqual(typeof(TException), ex.GetType(), string.Format("Expected exception of type {0} but type of {1} was thrown instead.", typeof(TException), ex.GetType()));
				Assert.AreEqual(expectedMessage, ex.Message, string.Format("Expected exception with a message of '{0}' but exceptino with message of '{1}' was thrown instead.", expectedMessage, ex.Message));
				return;
			}

			Assert.Fail(string.Format("Expected exception of type {0} but no exception was thrown.", typeof(TException)));
		}
	}
}